#include <string.h>
#include <iostream>

using std::cout;
using std::endl;

class Base
{
public:
    Base()
    : _pbase(nullptr)
    {
        cout << "Base()" << endl;
    }

    Base(const char *pbase)
    : _pbase(new char[strlen(pbase) + 1]())
    {
        cout << "Base(const char *)" << endl;
        strcpy(_pbase, pbase);
    }

    virtual
    void print() const
    {
        if(_pbase)
        {
            cout << "Base::_pbase = " << _pbase << endl;
        }
    }

    //如果将基类的析构函数设置为虚函数之后，派生类的析构函数会
    //自动成为虚函数，并且将派生类的虚函数的写法认为是一种独特
    //的重写,这是唯一的一个名字不一样的重写
    //
    //为什么可以这么做呢？
    //原因是：对于任何一个类而言，析构函数只有一个，不能进行重载
    //具备唯一性,对于编译器而言，对于任何一个类而言，都可以将
    //析构函数认为是~destructor()
    virtual
    ~Base()
    {
        cout << "~Base()" << endl;
        if(_pbase)
        {
            delete [] _pbase;
            _pbase = nullptr;
        }
    }
private:
    char *_pbase;
};

class Derived
: public Base
{
public:
    Derived(const char *pbase, const char *pderived)
    : Base(pbase)//借用基类构造函数
    , _pderived(new char[strlen(pderived) + 1]())
    {
        cout << "Derived(const char *, const char *)" << endl;
        strcpy(_pderived, pderived);
    }

    //重写
    void print() const override
    {
        Base::print();
        if(_pderived)
        {
            cout << "Derived::_pderived = " << _pderived << endl;
        }
    }

    ~Derived()
    {
        cout << "~Derived()" << endl;
        if(_pderived)
        {
            delete [] _pderived;
            _pderived = nullptr;
        }
    }
private:
    char *_pderived;
};

int main(int argc, char *argv[])
{
    cout << "sizeof(Base) = " << sizeof(Base) << endl;
    cout << "sizeof(Derived) = " << sizeof(Derived) << endl;

    cout << endl;
    Base *pbase = new Derived("hello", "world");
    /* Derived *pbase = new Derived("hello", "world");//ok */

    pbase->print();//多态

    //1、执行析构函数
    //2、执行operator delete
    /* delete dynamic_cast<Derived *>(pbase);//ok */
    delete pbase;//pbase->~destructor();--->pbase->~Base()
    pbase = nullptr;

    return 0;
}

